﻿var IoCC;
(function (IoCC) {
    "use strict";

    function has(container, key) {
        return Object.prototype.hasOwnProperty.call(container, key);
    }

    function get(container, key) {
        if (!has(container, key)) {
            throw "The key '" + key + "' is not registered.";
        }
        return container[key];
    }

    function set(container, key, factory, allowOverride) {
        if (typeof allowOverride === "undefined") { allowOverride = true; }
        if (has(container, key) && !allowOverride) {
            throw "The key '" + key + "' is already registered.";
        }
        container[key] = factory;
    }

    function remove(container, disposeCallbacks, key) {
        if (!has(container, key)) {
            throw "The key '" + key + "' is not registered.";
        }
        delete container[key];
        if (has(disposeCallbacks, key)) {
            delete disposeCallbacks[key];
        }
    }

    function makeSingleton(container, key) {
        var factory = get(container, key), created = false, result;

        set(container, key, function () {
            if (!created) {
                result = factory.apply(null, arguments);
                created = true;
            }
            return result;
        });
    }

    function makeDependent(container, key, dependencies) {
        var factory = get(container, key);
        set(container, key, function () {
            var dependencyValues = [], dependency, i;

            for (i = 0; i < dependencies.length; i++) {
                dependency = has(container, dependencies[i]) ? get(container, dependencies[i]) : null;
                if (!dependency) {
                    throw "Error wuile building '" + key + "': can't resolve the dependency '" + dependencies[i] + "'.";
                }
                dependencyValues.push(dependency());
            }

            return factory.apply(null, dependencyValues);
        });
    }

    function addDisposeCallback(disposeCallbaks, key, callback) {
        disposeCallbaks[key] = callback;
    }

    function wrap(value) {
        return function () {
            return value;
        };
    }

    function unwrap(value) {
        return value();
    }

    var DependencyBuilder = (function () {
        function DependencyBuilder(container, disposeCallbacks, key) {
            var _this = this;
            this.singleInstance = function () {
                makeSingleton(container, key);
                return _this;
            };
            this.requires = function () {
                var dependencies = [];
                for (var _i = 0; _i < (arguments.length - 0); _i++) {
                    dependencies[_i] = arguments[_i + 0];
                }
                makeDependent(container, key, dependencies);
                return _this;
            };
            this.dispose = function (callback) {
                addDisposeCallback(disposeCallbacks, key, callback);
                return _this;
            };
        }
        return DependencyBuilder;
    })();

    function makeContainer() {
        var factories = {}, disposeCallbacks = {};

        function container(key, factory) {
            if (arguments.length >= 2) {
                if (typeof factory === "function") {
                    set(factories, key, factory, false);
                } else if (factory === null) {
                    remove(factories, disposeCallbacks, key);
                } else {
                    set(factories, key, wrap(factory), false);
                }
                return new DependencyBuilder(factories, disposeCallbacks, key);
            } else {
                return unwrap(get(factories, key));
            }
        }
        container.clear = function () {
            factories = {};
            disposeCallbacks = {};
        };
        container.has = function (key) {
            return has(factories, key);
        };
        container.dispose = function () {
            var property;
            for (property in disposeCallbacks) {
                if (Object.prototype.hasOwnProperty.call(disposeCallbacks, property)) {
                    disposeCallbacks[property]();
                    disposeCallbacks[property] = null;
                }
            }
            factories = null;
            disposeCallbacks = null;
        };

        return container;
    }
    IoCC.makeContainer = makeContainer;
})(IoCC || (IoCC = {}));

var iocc = IoCC.makeContainer();
//# sourceMappingURL=jsiocc.js.map
